//
//  TTSocketClient.m
//  Socket
//
//  Created by Toj on 7/16/21.
//

#import "TTSocketClient.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>

//htons将一个无符号整型数据转为网络字节顺序，不同cpu是不同的顺序
#define SOCKET_PORT htons(80)
//ip地址：以本地为例子
#define SOCKET_ADRR inet_addr("127.0.0.1")

@interface TTSocketClient()

@property (assign, nonatomic) int socketId;

@end

@implementation TTSocketClient

- (instancetype)init {
    self = [super init];
    if (self) {
        [self sockte];
        [self connect];
        [self listener];
    }
    return self;
}

/// 初始化 socket
/** 创建socket
* int socket(int family, int type, int protocol);
* 参数一: family - 协议簇或者协议域
F_INET:   IPv4协议
AF_INET6: IPv6协议
AF_LOCAL: Unix域协议
AF_ROUTE: 路由套接字
AF_KEY:   密钥套接字

* 参数二: type - 套接字类型
SOCK_STREAM:   字节流套接字 TCP
SOCK_DGRAM:    数据包套接字 UDP
SOCK_EQPACKET: 有序分组套接字
SOCK_RAW:      原始套接字

* 参数三: protocol - 通信协议类型, 0: 自动选择根据第二个参数
IPPROTO_TCP: TCP传输协议
IPPROTO_UDP: UDP传输协议
IPPROTO_SCTP: SCTP传输协议
0:选择所给定family和type组合的系统默认值
*/
- (void)sockte {
   
    self.socketId = socket(AF_INET, SOCK_STREAM, 0);
    if (_socketId == -1) {
        NSLog(@"create socket fail");
        return;
    }
}

- (void)connect {
    //连接socket
    struct sockaddr_in serverAddress;
    struct in_addr socketIn_adrr;
    socketIn_adrr.s_addr = SOCKET_ADRR;
    
    // 协议簇或者协议域
    serverAddress.sin_family = AF_INET;
    // 端口
    serverAddress.sin_port = SOCKET_PORT;
    // 地址
    serverAddress.sin_addr = socketIn_adrr;
    /**
     * int connect(int sockfd, const struct sockaddr * servaddr, socklen_t addrlen)
     * 参数一: sockfd（socket描述符）
     * 参数二: servaddr（socket地址结构体指针）
     * 参数三: addrlen（socket地址结构体大小）
     * 返回值: 0代表成功, 其他代表成功
     */
    // 终端 【nc -lk 123456】监听123456端口
    // netcat -> nc
    int result = connect(self.socketId, (const struct sockaddr *)&serverAddress, sizeof(serverAddress));
    
    if(result != 0){
        NSLog(@"客户端：连接失败");
        return;
    }
}

- (void)listener {
    ///异步接受信息，防止阻塞主线程
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [self recvMsg];
    });
}
- (void)recvMsg{
    while (1) {
        uint8_t buffers[1024];
        ///ssize_t recv(int, void *, size_t, int)
        ///参数一：socket标志符
        ///参数二：缓冲区
        ///参数三：缓冲区大小
        ///参数四：指定调用方式，一般设置为0
        ssize_t sizeLen = recv(self.socketId, buffers, sizeof(buffers), 0);
        NSLog(@"客户端：接收到%zd个字节",sizeLen);
        if(sizeLen == 0){
            continue;
        }
        NSData *data = [NSData dataWithBytes:buffers length:sizeLen];
        NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"客户端：%@ 接收到消息：%@",[NSThread currentThread],msg);
    }
}

- (void)sendMessag:(NSString *)msg{
    if(msg.length <= 0) return;
    const void *buff = msg.UTF8String;
    ///ssize_t = write(int __fd, const void * __buf, size_t __nbyte)
    ///参数一：socket标志符
    ///参数二：缓冲区
    ///参数三：缓冲区大小
    // ssize_t sizeLen = write(self.socketId, buff, strlen(buff));
    
    ssize_t sizeLen = send(self.socketId, buff, strlen(buff), 0);
    write(self.socketId, buff, strlen(buff));
    
    NSLog(@"客户端：发送%zd字节消息",sizeLen);
}

//static TTSocketClient* _instance = nil;
//+ (instancetype)shareManager {
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        _instance = [[super allocWithZone:NULL] init];
//    });
//    return _instance ;
//}
//
//+ (id)allocWithZone:(struct _NSZone *)zone {
//    return [self shareManager];
//}
//
//- (id)copyWithZone:(struct _NSZone *)zone {
//    return [self.class shareManager];
//}

@end
